<template>
    <view class="code-input-container">
        <view
            v-for="(item, index) in codeList"
            :key="index"
            class="code-cell"
            :class="{
                'code-cell--focus': focusIndex === index,
                [`code-cell--${mode}`]: true
            }"
            @click="handleCellClick(index)"
        >
            {{ valueArr[index] || '' }}
        </view>

        <!-- 隐藏的原生 input 用于获取焦点 -->
        <input
            ref="inputRef"
            type="text"
            v-model="inputValue"
            maxlength="6"
            class="hidden-input"
            @input="onInput"
            @focus="onFocus"
            @blur="onBlur"
        />
    </view>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'

const props = defineProps<{
    length?: number // 验证码长度，默认 6
    mode?: 'box' | 'line' | 'circle' // 样式模式
    modelValue?: string // 双向绑定值
}>()

const emit = defineEmits<{
    (e: 'update:modelValue', val: string): void
    (e: 'finish', val: string): void
}>()

const inputRef = ref<HTMLInputElement | null>(null)
const focusIndex = ref<number>(0)

// 初始化输入框数组
const codeList = Array.from({ length: props.length || 8 }, (_, i) => i)
const valueArr = computed(() => {
    const arr = props.modelValue?.split('') || []
    return arr.concat(Array(codeList.length - arr.length).fill(''))
})

// 输入处理
const inputValue = computed({
    get: () => props.modelValue || '',
    set: (val) => {
        emit('update:modelValue', val)
    }
})

const onInput = (e: Event) => {
    const target = e.target as HTMLInputElement
    let val = target.value.replace(/[^0-9a-zA-Z]/g, '').slice(0, props.length || 6)
    emit('update:modelValue', val)

    // 自动触发 finish 事件
    if (val.length === props.length) {
        emit('finish', val)
    }
}

const onFocus = () => {
    focusIndex.value = props.modelValue?.length || 0
}

const onBlur = () => {
    focusIndex.value = -1
}

const handleCellClick = (index: number) => {
    focusIndex.value = index
    if (inputRef.value && inputRef.value.focus) {
        inputRef.value.focus()
    }
}
</script>

<style lang="scss" scoped>
.code-input-container {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
    position: relative;
}

.code-cell {
    flex: 1;
    max-width: 60px;
    height: 50px;
    line-height: 50px;
    text-align: center;
    font-size: 20px;
    border-bottom: 1px solid #ccc;
    margin: 0 4px;

    &--box {
        border: 1px solid #ccc;
        border-radius: 4px;
    }

    &--line {
        border-bottom: 2px solid #ccc;
    }

    &--circle {
        border: 1px solid #ccc;
        border-radius: 50%;
    }

    &--focus {
        border-color: #f9b85e !important;
        outline: none;
    }
}

.hidden-input {
    position: absolute;
    opacity: 0;
    z-index: -1;
    height: 0;
    width: 0;
    pointer-events: none;
}
</style>
